package com.example.teacher;

import android.util.Log;

import com.orhanobut.hawk.Hawk;

import org.json.JSONException;
import org.json.JSONObject;
import org.webrtc.IceCandidate;
import org.webrtc.PeerConnection;
import org.webrtc.SessionDescription;

import java.net.URISyntaxException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import io.socket.client.IO;
import io.socket.client.Socket;
import io.socket.emitter.Emitter;

/**
 * Created by chao on 2019/1/30.
 */

public class SignalingClient2 {
    private static final String TAG = "SignalingClient";
    private static SignalingClient2 instance;
    private String userId;
    private List<String>stringList=new ArrayList<>();
    private List<String>stringKey=new ArrayList<>();
   private List<HashMap<String ,PeerConnection  >>hashMapList=new ArrayList<>();
   private List<PeerConnection>peerConnectionList=new ArrayList<>();
  private  boolean meIsInfirst=false;
    private SignalingClient2(){}
    public static SignalingClient2 get() {
        if(instance == null) {
            synchronized (SignalingClient2.class) {
                if(instance == null) {
                    instance = new SignalingClient2();

                }
            }
        }
        return instance;
    }

    private Socket socket;
    private String room = "2";
    private Callback callback;


    private final TrustManager[] trustAll = new TrustManager[]{
            new X509TrustManager() {
                @Override
                public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {

                }

                @Override
                public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {

                }

                @Override
                public X509Certificate[] getAcceptedIssuers() {
                    return new X509Certificate[0];
                }
            }
    };

    public void init(Callback callback) {
        this.callback = callback;
           /* SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null, trustAll, null);
            IO.setDefaultHostnameVerifier((hostname, session) -> true);
            IO.setDefaultSSLContext(sslContext);*/
//          userId=new StringBuilder("studen");
            IO.Options opts = new IO.Options();
            opts.forceNew = false;
            opts.reconnection = true;
            opts.reconnectionDelay = 2000;      //延迟
            opts.reconnectionDelayMax = 6000;
            opts.reconnectionAttempts = -1;
            opts.timeout = 6000;
            if (socket == null) {
                try {
                   // socket = IO.socket("http://192.168.8.154:5000",opts);
                   socket = IO.socket("http://42.192.180.207:3001",opts);
                    socket.connect();
                    addHandles();
                } catch (URISyntaxException e) {
                    e.printStackTrace();
                }
            }
           /* socket = IO.socket("http://192.168.8.141:3000",opts);*/
    /*    if (Hawk.contains("userId")){
            userId=Hawk.get("userId");

        }*/
        JSONObject data2 = new JSONObject();
      //  userId.append("studen");
        userId = new StringBuffer("studen").append(UUIDUtil.get16UUID()).toString();
     //   userId="xx";
        try {
            data2.put("user_id",userId);//以socket id 作为 userId;
        } catch (JSONException e) {
            e.printStackTrace();
        }
        Log.d(TAG+"data2=", data2.toString()+"   =");
        if (Hawk.contains("examRoomCode")){
            room=Hawk.get("examRoomCode");
        }
        socket.emit("join", room,data2);
            socket.on("full", args -> {
                Log.e(TAG+"chao", "room full");
            });

        // 其他用户加入通知
            socket.on("join", args -> {
                //Log.d("wthwhw",args[3]);
                UserInfo userInfo = new UserInfo();
                Log.d(TAG, "peer joined222 " + args[3].toString());
               /* stringList.clear();
                hashMapList.clear();*/
               // stringKey.clear();拒绝清空，做去重处理。
                stringList.clear();
               String aa= args[3].toString().substring(1,args[3].toString().length()-1);

               String[]str=aa.split(",");
                for (int i=0;i<str.length;i++){
                    str[i].substring(1, str[i].length()-1);
                    stringList.add(str[i].substring(1, str[i].length()-1));
                }
                Log.d(TAG, "peer joined " + Arrays.toString(args));
                int num=Integer.valueOf(args[2].toString());
                if(stringList != null && stringList.size() > 1){
//                    if(stringKey != null && stringKey.size ()> 0){
                        for(int i = 0; i < stringList.size(); i++){
                           String sysUserId = stringList.get(i);
                           if (sysUserId.length()>=6){
                               String  stu=sysUserId.substring(0,6);
                               if ("studen".equals(stu)){
                                   continue;

                               }
                           }

                            if(!userId.equals(sysUserId)){
                                String peerId = null;
                                if(stringKey.size () == 0 || (!stringKey.contains(userId+"-"+sysUserId)&&!stringKey.contains(sysUserId+"-"+userId))){
                                    //创建链接
                            String fromSocketId=String.valueOf(args[4]);

                                    if (userId.equals(fromSocketId)) {
                                        peerId = sysUserId + "-" + userId;
                                        callback.CreatePeerConnnect(peerId);//创建连接
                                        callback.onPeerJoined(peerId);

                                    }else {
                                        peerId = userId + "-" + sysUserId;
                                        callback.CreatePeerConnnect(peerId);//创建连接
                                    }
                                    stringKey.add(peerId);

                                }else {
                                    if (stringKey.contains(userId+"-"+sysUserId)){
                                        peerId = userId+"-"+sysUserId;
                                    }else {
                                        peerId = sysUserId+"-"+userId;
                                    }
                                }
                                //发offer
//                                callback.onPeerJoined(peerId);
                            }

                        }
//                    }
                }
           /*     if (stringKey.size() > 0){

                    for (String key:stringKey) {
                        callback.onPeerJoined(key);
                    }
                }*/
                Log.d("leave1111", "leavestringList= " + stringList.size()+"   leavestringKey="+stringKey.size());
            });


        socket.on("err", args -> {
            Log.d(TAG, "err= " + args[0]);
           // callback.onPeerJoined(String.valueOf(args[1]));
        });
       /* //监听事件:新用户加入通知
        socket.on("join", args -> {
            Log.d(TAG, "room created:" + socket.id());
            callback.onCreateRoom();
        });*/
            socket.on("joined", args -> {
                Log.d(TAG, "self joined:" + socket.id());
                callback.onSelfJoined();
            });
            socket.on("log", args -> {
                Log.d(TAG, "log call " + Arrays.toString(args));
            });
            socket.on("bye", args -> {
                Log.d("chao", "bye " + args[0]);
               // callback.onPeerLeave((String) args[0]);
            });
        //主要是收到端对端的消息 进行处理
            socket.on("message", args -> {

                Object arg = args[1];

                if (arg instanceof String) {

                } else if (arg instanceof JSONObject) {
                    Log.d(TAG+"8888", "message " +  Arrays.toString(args));
                    JSONObject data = (JSONObject) arg;
                    JSONObject d = data.optJSONObject("data");
                    String type = d.optString("type");

                  /*  Log.d(TAG+"99", "message " +  d.optString("type"));
                    Log.d(TAG+"99", "message " +  d.optString("sdp"));
                    Log.d(TAG+"99", "message " +  d.optString("account"));*/

                    Log.d("JSONObject===", "bye==" + type);
                    if ("offer".equals(type)) {
                        callback.onOfferReceived(data);
                    } else if ("answer".equals(type)) {
                        callback.onAnswerReceived(data);
                    } else if ("candidate".equals(type)) {
                        callback.onIceCandidateReceived(data);
                    }
                }
            });
        //监听其他人离开房间，移除包含离开人的所有PeerConnnect连接
        socket.on("closeChannel", args -> {
            //去除【】 split(",") ["1","978e61aaa98547a5"]取第二个值  离开人员的id
            //String aa=args[0].toString().substring(1,args[0].toString().length()-1);
            String aa=Arrays.toString(args).substring(1,Arrays.toString(args).length()-1);
          String []leaveIdStr= aa.split(",");
          String leaveId=leaveIdStr[1].toString();
            callback.onLeaveRoom(leaveId);
          //移除当前缓存的当前离开人人ID；
            for (int i=0;i<stringList.size();i++){
                if (leaveId.equals(stringList.get(i))){
                    stringList.remove(i);
                }

          }

            for(int i=0;i<stringKey.size();i++){
                String[]strs = stringKey.get(i).split("-");
             for (int k=0;k<strs.length;k++){
                 if (leaveId.trim().equals(strs[k].trim())){
                     stringKey.remove(i);
                 }
             }
            }

        /*    if (arg instanceof String) {

            } else if (arg instanceof JSONObject) {


            }*/
        });
        }

    private  void addHandles() {
        /*
         * 断开连接
         * */
        socket.on(Socket.EVENT_DISCONNECT, new Emitter.Listener() {
            @Override
            public void call(Object... args) {

                Log.i(TAG, "连接断开");

            }
        });

        socket.on(Socket.EVENT_CONNECT, new Emitter.Listener() {
            @Override
            public void call(Object... args) {
                Log.i(TAG, "连接中");


            }
        });

        socket.on(Socket.EVENT_CONNECT_ERROR, new Emitter.Listener() {
            @Override
            public void call(Object... args) {
                Log.i(TAG, "连接失败=="+args[0].toString()+"===="+ args[0].hashCode());

            }
        });

        socket.on(Socket.EVENT_CONNECT, new Emitter.Listener() {
            @Override
            public void call(Object... args) {
                Log.i(TAG, "连接成功");

            }
        });}
    public void destroy() {
        if (socket!=null){
            socket.disconnect();
            socket.close();
            instance = null;
        }

    }

    public void sendIceCandidate(IceCandidate iceCandidate, String to) {
        JSONObject jo = new JSONObject();
        JSONObject conten = new JSONObject();
        try {
            conten.put("type", "candidate");
            conten.put("label", iceCandidate.sdpMLineIndex);
            conten.put("id", iceCandidate.sdpMid);
            conten.put("candidate", iceCandidate.sdp);
           /* jo.put("from", socket.id());*/
            jo.putOpt("data",conten);
            jo.putOpt("account", to);
         //   Log.d("sdsdd",iceCandidate.sdp);
            socket.emit("message", room,jo);
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    public void sendSessionDescription(SessionDescription sdp, String to) {
        JSONObject jo = new JSONObject();
        JSONObject conten = new JSONObject();
        try {
            conten.put("type", sdp.type.canonicalForm());
            conten.put("sdp", sdp.description);
            /* jo.put("from", socket.id());*/
            jo.putOpt("data",conten);
            jo.putOpt("account", to);

//            jo.put("type", sdp.type.canonicalForm());
//            jo.put("sdp", sdp.description);
//            jo.put("to", to);*/
            socket.emit("message", room,jo);
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }
    public  void leaveRoom(){
        //socket.emit("leave", room);
    }
    public interface Callback {
        void onCreateRoom();
        void onPeerJoined(String socketId);
        void onSelfJoined();
        void onLeaveRoom(String msg);
        void onOfferReceived(JSONObject data);
        void onAnswerReceived(JSONObject data);
        void onIceCandidateReceived(JSONObject data);
        void CreatePeerConnnect(String str);
    }

}
